/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "communicate_interface.h"

#include <thread>
#include "spatial_awareness_common.h"
#include "spatial_awareness_mgr_service.h"

namespace OHOS {
namespace Msdp {
namespace {
auto g_service = DelayedSpSingleton<SpatialaWarenessMgrService>::GetInstance();
constexpr int SLEEP_TIME = 2000;
}
void CommunicateInterface::RegisterListoner(const std::shared_ptr<RemoteListener>& remoteListener)
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    remoteListener_ = std::move(remoteListener);
    SoftbusSessionListener::RegisterListoner(remoteListener_);
    SpatialDeviceManager::RegisterListoner(remoteListener_);
}

int CommunicateInterface::PublishService()
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    remoteListener_->OnPublishSuccess();
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::GetTrustDeviceList()
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    remoteDeviceInfoList_.clear();
    std::vector<DistributedHardware::DmDeviceInfo> deviceList;
    g_service->GetDeviceManager()->GetTrustedDeviceList();
    g_service->GetDeviceManager()->TransferTrustedDeviceList(deviceList);

    if (deviceList.size() == 0) {
        SPATIAL_LOGI(MODULE_SERVICE, "deviceList is empty");
        remoteListener_->OnGetFail(remoteDeviceInfoList_);
        return SPATIALMANAGER_FAILED;
    }
    for (auto info = deviceList.begin(); info != deviceList.end(); info++) {
        DeviceInfo deviceInfo;
        deviceInfo.deviceId = info->deviceId;
        deviceInfo.typeId  = info->deviceTypeId;
        deviceInfo.deviceName = info->deviceName;
        SPATIAL_LOGI(MODULE_SERVICE, "%{public}s OpenSoftbusSession, peerDeviceId:%{public}s, typeId=%{public}x",
            __func__, deviceInfo.deviceId.c_str(), deviceInfo.typeId);
        SPATIAL_LOGI(MODULE_SERVICE, "%{public}s insert remote device list", __func__);
        remoteDeviceInfoList_.push_back(deviceInfo);
    }
    remoteListener_->OnGetSuccess(remoteDeviceInfoList_);
    return SPATIALMANAGER_OK;
}

DeviceInfo CommunicateInterface::GetLocalDeviceInfo()
{
    DistributedHardware::DmDeviceInfo dmInfo;
    g_service->GetDeviceManager()->GetOwnDeviceInfo(dmInfo);
    DeviceInfo deviceInfo;
    deviceInfo.deviceId = dmInfo.deviceId;
    deviceInfo.deviceName = dmInfo.deviceName;
    deviceInfo.typeId = dmInfo.deviceTypeId;
    return deviceInfo;
}

int CommunicateInterface::StartDiscovery()
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::StopDiscovery()
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    remoteListener_->OnDiscoverEnd();
    remoteListener_->OnError(ERROR_DISCOVER_FAILED);
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::RegisterDevStateCallback()
{
    int ret = g_service->GetDeviceManager()->RegisterDevStateCallback();
    if (ret != SPATIALMANAGER_OK) {
        return ret;
    }
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::UnRegisterDevStateCallback()
{
    int ret = g_service->GetDeviceManager()->UnRegisterDevStateCallback();
    if (ret != SPATIALMANAGER_OK) {
        return ret;
    }
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::Connect(const DeviceInfo& device)
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s first size = %{public}d", __func__, remoteDeviceInfoList_.size());
    remoteListener_->OnConnected(device.networkId);
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::Disconnect()
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    if (remoteListener_ == nullptr) {
        SPATIAL_LOGE(MODULE_SERVICE, "remoteListener_ is nullptr");
        return SPATIALMANAGER_FAILED;
    }
    remoteListener_->OnDisconnected();
    remoteListener_->OnError(ERROR_CONNECT_FAILED);
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::CreateSessionServer()
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    SpatialSoftbusSession::GetInstance().Start();
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::RemoveSessionServer()
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    SpatialSoftbusSession::GetInstance().Stop();
    remoteListener_->OnError(ERROR_SESSION_FAILED);
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::OpenSession(const std::string &peerDeviceId, int &sessionId)
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME));
    int networkId = SpatialSoftbusSession::GetInstance().OpenSoftbusSession(peerDeviceId);
    sessionId = networkId;
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::CloseSession(int32_t sessionId)
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    SpatialSoftbusSession::GetInstance().CloseSession(sessionId);
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::SendBytes(int sessionId, const void *data, unsigned int len)
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    int ret = SpatialSoftbusSession::GetInstance().SendBytes(sessionId, data, len);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_SERVICE, "%{public}s failed to send bytes", __func__);
        remoteListener_->OnError(ERROR_SEND_FAILED);
        return SPATIALMANAGER_FAILED;
    }
    return SPATIALMANAGER_OK;
}

int CommunicateInterface::SendMessage(int sessionId, const void *data, unsigned int len)
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    int32_t ret = SpatialSoftbusSession::GetInstance().SendMsg(sessionId, data, len);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_SERVICE, "%{public}s failed to send message", __func__);
        remoteListener_->OnError(ERROR_SEND_FAILED);
        return ret;
    }
    return SPATIALMANAGER_OK;
}

bool CommunicateInterface::IsServer(int sessionId)
{
    SPATIAL_LOGI(MODULE_SERVICE, "%{public}s enter", __func__);
    return SpatialSoftbusSession::GetInstance().IsServer(sessionId);
}

int CommunicateInterface::GetPeerDeviceId(int sessionId, std::string &peerDeviceId)
{
    int ret = SpatialSoftbusSession::GetInstance().GetPeerDeviceId(sessionId, peerDeviceId);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_SERVICE, "%{public}s failed to get peerId", __func__);
        return ret;
    }
    return SPATIALMANAGER_OK;
}
} // namespace Msdp
} // namespace OHOS